import BTNode from './Base/BTNode';
import BTParent from './Base/BTParent';
import BTTree from './Base/BTTree';
import { NodeStatus } from '../common/Enum';

export class BehaviorManager {

    tree: BTTree
    /** 所有节点的容器 */
    nodeList: BTNode[] = []
    /** 运行栈 */
    activeStack: number[] = []
    /** 运行栈父节点索引，-1表示没有父节点 */
    parentIndex: number[] = []
    /** 子节点索引，行为、条件节点没有子节点索引 */
    childrenIndex: number[][] = []

    restartWhenCompelete = true
    constructor(tree: BTTree) {
        this.tree = tree
        if (this.tree.root) {
            this.activeStack.push()
            this.parentIndex.push(-1)
            this.addToNodeList(this.tree.root, { parentCompositeIndex: -1 })
            this.pushNode(0)
        }
    }
    restart() {
        this.pushNode(0)
    }

    /** 双向标记 父节点子节点，子节点父节点 */
    addToNodeList(node: BTNode, data: { parentCompositeIndex: number }) {
        this.nodeList.push(node)
        const index = this.nodeList.length - 1
        if (node instanceof BTParent) {
            this.childrenIndex.push([])
            for (let i = 0; i < node.children.length; i++) {
                this.parentIndex.push(index)
                this.childrenIndex[index].push(this.nodeList.length)
                this.addToNodeList(node.children[i], data)
            }
        } else {
            this.childrenIndex.push([])
        }
    }

    tick(dt: number) {
        this.tree.dt = dt

        let prevIndex = -1
        let prevStatus = NodeStatus.Inactive
        while (this.activeStack.length) {

            const curIndex = this.activeStack.length - 1
            if (curIndex === prevIndex) {
                break
            }
            prevIndex = curIndex
            prevStatus = this.runNode(this.activeStack[curIndex], prevStatus)
        }
    }

    runNode(index: number, prevStatus: NodeStatus) {
        this.pushNode(index)
        const node = this.nodeList[index]
        let status = prevStatus

        if (node instanceof BTParent) {
            status = this.runParentNode(index, status)
        } else {
            status = node.onUpdate()
        }

        if (status !== NodeStatus.Running) {
            this.popNode(index, status)
        }

        return status
    }

    runParentNode(index: number, status: NodeStatus) {
        const node = this.nodeList[index] as BTParent
        let childStatus = NodeStatus.Inactive
        // 当前节点可执行，并且子节点不为running
        while (node.canExecute() && childStatus !== NodeStatus.Running) {
            childStatus = status = this.runNode(this.childrenIndex[index][node.index], status)
        }
        return status
    }

    /** 入栈节点，index节点索引 */
    pushNode(index: number) {
        if (this.activeStack.length === 0 || this.activeStack[this.activeStack.length - 1] !== index) {
            this.activeStack.push(index)
            const node = this.nodeList[index]
            node.onStart()
        }
    }

    popNode(index: number, status: NodeStatus) {
        this.activeStack.pop()
        const node = this.nodeList[index]
        node.onEnd()
        const parentIndex = this.parentIndex[index]
        if (parentIndex !== -1) {

            const parentNode = this.nodeList[parentIndex] as BTParent
            parentNode.onChildExecuted(status)
        }

        if (this.activeStack.length === 0 && this.restartWhenCompelete) {
            this.restart()
        }

    }

}
